package com.doublecheck.project.client;

import java.util.ArrayList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.editor.client.Editor.Path;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.chart.client.chart.Chart;
import com.sencha.gxt.chart.client.chart.Legend;
import com.sencha.gxt.chart.client.chart.axis.CategoryAxis;
import com.sencha.gxt.chart.client.chart.axis.NumericAxis;
import com.sencha.gxt.chart.client.chart.series.LineSeries;
import com.sencha.gxt.chart.client.chart.series.Primitives;
import com.sencha.gxt.chart.client.chart.series.SeriesLabelProvider;
import com.sencha.gxt.chart.client.chart.series.SeriesToolTipConfig;
import com.sencha.gxt.chart.client.draw.Color;
import com.sencha.gxt.chart.client.draw.RGB;
import com.sencha.gxt.chart.client.draw.path.PathSprite;
import com.sencha.gxt.chart.client.draw.sprite.Sprite;
import com.sencha.gxt.chart.client.draw.sprite.TextSprite;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;
import com.sencha.gxt.fx.client.Draggable;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Resizable;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.Resizable.Dir;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.event.CollapseEvent;
import com.sencha.gxt.widget.core.client.event.ExpandEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.CollapseEvent.CollapseHandler;
import com.sencha.gxt.widget.core.client.event.ExpandEvent.ExpandHandler;
import com.sencha.gxt.widget.core.client.event.HideEvent.HideHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;

public class LineChart extends Chart<Item> {
	/*
	 * Metadata for Line Chart
	 */
	private ArrayList<Item> data;
	private String X_axis;
	private String Y_axis;
	
	private Window window;
	private ContentPanel panel;
	private VerticalLayoutContainer layout;
	
	public LineChart(int numOfSeries, LineChart_Dataset dataset, String title,
			String X_axis, AxisType X_type, String Y_axis, AxisType Y_type) {
		this.data = dataset.getDataset();
		this.X_axis = X_axis;
		this.Y_axis = Y_axis;
	}

	public LineChart() {}
	
	public interface DataPropertyAccess extends PropertyAccess<Item> {
		ValueProvider<Item, Double> value0();
		ValueProvider<Item, Double> value1();
		ValueProvider<Item, Double> value2();		
		ValueProvider<Item, String> category();

		@Path("category")
		ModelKeyProvider<Item> categoryKey();
	}

	private static final DataPropertyAccess dataAccess = GWT.create(DataPropertyAccess.class);

	@Override
	public Widget asWidget() {
		final ListStore<Item> store = new ListStore<Item>(dataAccess.categoryKey());
		Chart<Item> chart = new Chart<Item>();
		store.addAll(data);
		chart.setStore(store);
		chart.setShadow(true);	
	
		/*For numerical axis*/
	    NumericAxis<Item> axis = new NumericAxis<Item>();
	    axis.setPosition(Position.LEFT);
	    axis.addField(dataAccess.value0());
	    axis.addField(dataAccess.value1());
	    axis.addField(dataAccess.value2());
	    TextSprite title = new TextSprite(X_axis);
	    title.setFontSize(18);
	    axis.setTitleConfig(title);
	    axis.setMinorTickSteps(1);
	    axis.setDisplayGrid(true);
	    PathSprite odd = new PathSprite();
	    odd.setOpacity(1);
	    odd.setFill(new Color("#ddd"));
	    odd.setStroke(new Color("#bbb"));
	    odd.setStrokeWidth(0.5);
	    axis.setGridOddConfig(odd);
	    axis.setMinimum(0);
	    axis.setMaximum(100);
	    chart.addAxis(axis);
	    /*For category axis*/
	    CategoryAxis<Item, String> catAxis = new CategoryAxis<Item, String>();
	    catAxis.setPosition(Position.BOTTOM);
	    catAxis.setField(dataAccess.category());
	    title = new TextSprite(Y_axis);
	    title.setFontSize(18);
	    catAxis.setTitleConfig(title);
	    chart.addAxis(catAxis);
	 
	    final LineSeries<Item> series = new LineSeries<Item>();
	    series.setYAxisPosition(Position.LEFT);
	    series.setYField(dataAccess.value0());
	    series.setStroke(new RGB(194,0,36));
	    series.setShowMarkers(true);
	    Sprite marker = Primitives.square(0, 0, 6);
	    marker.setFill(new RGB(194,0,36));
	    series.setMarkerConfig(marker);
	    series.setHighlighting(true);
	    chart.addSeries(series);
	 
	    final LineSeries<Item> series2 = new LineSeries<Item>();
	    series2.setYAxisPosition(Position.LEFT);
	    series2.setYField(dataAccess.value1());
	    series2.setStroke(new RGB(240,165,10));
	    series2.setShowMarkers(true);
	    series2.setSmooth(true);
	    marker = Primitives.circle(0, 0, 6);
	    marker.setFill(new RGB(240,165,10));
	    series2.setMarkerConfig(marker);
	    series2.setHighlighting(true);
	    chart.addSeries(series2);
	 
	    final LineSeries<Item> series3 = new LineSeries<Item>();
	    series3.setYAxisPosition(Position.LEFT);
	    series3.setYField(dataAccess.value2());
	    series3.setStroke(new RGB(32, 68, 186));
	    series3.setShowMarkers(true);
	    series3.setSmooth(true);
	    series3.setFill(new RGB(180,180,180));
	    marker = Primitives.diamond(0, 0, 6);
	    marker.setFill(new RGB(32, 68, 186));
	    series3.setMarkerConfig(marker);
	    series3.setHighlighting(true);
	    chart.addSeries(series3);	    
	    
	    /*Mouse over event for sprites*/
		SeriesToolTipConfig<Item> tooltip = new SeriesToolTipConfig<Item>();
	    tooltip.setLabelProvider(new SeriesLabelProvider<Item>() {
	    	@Override
	        public String getLabel(Item item, ValueProvider<? super Item, ? extends Number> valueProvider) {
	    		String output = dataAccess.category().getValue(item) + ":" + String.valueOf(valueProvider.getValue(item));
	    		return output;
	    	}
	    });
	    tooltip.setDismissDelay(2000);
	    series3.setToolTipConfig(tooltip);
	    series2.setToolTipConfig(tooltip);
	    series.setToolTipConfig(tooltip);
	    /*Set legend of chart*/
	    final Legend<Item> legend = new Legend<Item>();
	    legend.setPosition(Position.RIGHT);
	    legend.setItemHighlighting(true);
	    legend.setItemHiding(true);
	    chart.setLegend(legend);	    
	    /*For contain panel*/
	    panel = new FramedPanel();
	    panel.getElement().getStyle().setMargin(10, Unit.PX);
	    panel.setCollapsible(true);
	    panel.setHeadingText("Line Chart");
	    panel.setPixelSize(400, 320);
	    panel.setBodyBorder(true);	     
	    final Resizable resize = new Resizable(panel, Dir.E, Dir.SE, Dir.S);
	    resize.setMinHeight(400);
	    resize.setMinWidth(400);
	    new Draggable(panel, panel.getHeader()).setUseProxy(false);	 
	     
	    panel.addExpandHandler(new ExpandHandler() {
	      @Override
	      public void onExpand(ExpandEvent event) {
	        resize.setEnabled(true);
	      }
	    });
	    panel.addCollapseHandler(new CollapseHandler() {
	      @Override
	      public void onCollapse(CollapseEvent event) {
	        resize.setEnabled(false);
	      }
	    }); 	   	    
	    
	    chart.setLayoutData(new VerticalLayoutData(1, 1));	
	    layout = new VerticalLayoutContainer();
	    layout.add(chart);
	    layout.setLayoutData(new VerticalLayoutData(1, 1));	    
	    initiateWindow();	    
	 
	    return panel;	    
	}
	/*For zoom-in event of the chart*/
	public void initiateWindow(){
		final VerticalLayoutContainer panelLayout = new VerticalLayoutContainer();
		final ToolBar toolBar = new ToolBar();		
		window = new Window();
	    window.setPixelSize(900, 700);
	    window.setModal(true);
	    window.setBlinkModal(true);	    
	    window.setHeadingText("Line Chart");
	    window.addHideHandler(new HideHandler() {
	        @Override
	        public void onHide(HideEvent event) {
	            TextButton open = ((Window) event.getSource()).getData("open");
	            open.focus();
	            panelLayout.clear();
	            panelLayout.add(toolBar);
	            panelLayout.add(layout);
				panel.add( panelLayout);
	        }
	    });
	    /*Close button at the bottom of window*/
		TextButton closeBtn = new TextButton("Close");
		closeBtn.addSelectHandler(new SelectHandler() {
			@Override
			public void onSelect(SelectEvent event) {
				panelLayout.clear();
		        panelLayout.add(toolBar);
		        panelLayout.add(layout);
				panel.add(panelLayout);
				window.hide();
			}
		});
		window.addButton(closeBtn);
		window.setFocusWidget(window.getButtonBar().getWidget(0));
		/*zoom-in button on toolbar*/	    
	    TextButton openBtn = new TextButton("Zoom In");
	    openBtn.addSelectHandler(new SelectHandler() {
	    	@Override
	    	public void onSelect(SelectEvent event) {
	    		window.add(layout);
	    		window.show();
	    	}
	    });
	    window.setData("open", openBtn);	    	    
	    toolBar.add(openBtn);
	    toolBar.setLayoutData(new VerticalLayoutData(1, -1));
	    	    
        panelLayout.add(toolBar);
        panelLayout.add(layout);	
		panel.add(panelLayout);
	}
}

